﻿Imports System.ComponentModel
Imports System.Web.UI
Imports System.Web.UI.WebControls

Namespace Controls
    ''' <summary> 
    ''' 文本框控件 
    ''' </summary> 
    <DefaultProperty("Text"), ToolboxData("<{0}:TextBox runat=server></{0}:TextBox>"), Designer("System.Web.UI.Design.WebControls.PreviewControlDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")> _
    Public Class TextBox
        Inherits System.Web.UI.WebControls.TextBox
        Implements IWebControl
        ''' <summary> 
        ''' RequiredFieldValidator控件变量 
        ''' </summary> 
        Protected CanBeNullRFV As System.Web.UI.WebControls.RequiredFieldValidator = New RequiredFieldValidator()

        ''' <summary> 
        ''' RegularExpressionValidator控件变量 
        ''' </summary> 
        Protected RequiredFieldTypeREV As System.Web.UI.WebControls.RegularExpressionValidator = New RegularExpressionValidator()

        ''' <summary> 
        ''' RangeValidator控件变量 
        ''' </summary> 
        Protected NumberRV As New System.Web.UI.WebControls.RangeValidator()

        ''' <summary> 
        ''' 构造函数 
        ''' </summary> 
        Public Sub New()
            MyBase.New()
            MyBase.Attributes.Add("onfocus", "this.className='FormFocus';")
            MyBase.Attributes.Add("onblur", "this.className='FormBase';")
            'base.BorderStyle = BorderStyle.Dotted; 
            'base.BorderWidth = 1; 
            MyBase.CssClass = "FormBase"
        End Sub

        ''' <summary> 
        ''' 添加属性方法 
        ''' </summary> 
        ''' <param name="key">键值,如class等</param> 
        ''' <param name="valuestr">要绑定的字符串</param> 
        Public Sub AddAttributes(ByVal key As String, ByVal valuestr As String)
            Me.Attributes.Add(key, valuestr)
        End Sub

        ''' <summary> 
        ''' 创建子控件 
        ''' </summary> 
        Protected Overloads Overrides Sub CreateChildControls()
            '当指定了输入框的最小或最大值时,则加入校验范围项 
            If Me.MaximumValue IsNot Nothing OrElse Me.MinimumValue IsNot Nothing Then
                NumberRV.ControlToValidate = Me.ID
                NumberRV.Type = ValidationDataType.[Double]

                If Me.MaximumValue IsNot Nothing AndAlso Me.MinimumValue IsNot Nothing Then
                    NumberRV.MaximumValue = Me.MaximumValue
                    NumberRV.MinimumValue = Me.MinimumValue
                    NumberRV.ErrorMessage = "当前输入数据应在" + Me.MinimumValue + "和" + Me.MaximumValue + "之间!"
                Else
                    If Me.MaximumValue IsNot Nothing Then
                        NumberRV.MaximumValue = Me.MaximumValue
                        NumberRV.MinimumValue = Int32.MinValue.ToString()
                        NumberRV.ErrorMessage = "当前输入数据允许最大值为" + Me.MaximumValue
                    End If
                    If Me.MinimumValue IsNot Nothing Then
                        NumberRV.MinimumValue = Me.MinimumValue
                        NumberRV.MaximumValue = Int32.MaxValue.ToString()
                        NumberRV.ErrorMessage = "当前输入数据允许最小值为" + Me.MinimumValue
                    End If
                End If
                NumberRV.Display = ValidatorDisplay.[Static]
                Me.Controls.AddAt(0, NumberRV)
            End If

            If (RequiredFieldType IsNot Nothing) AndAlso (RequiredFieldType <> "") AndAlso (RequiredFieldType <> "暂无校验") Then
                RequiredFieldTypeREV.Display = System.Web.UI.WebControls.ValidatorDisplay.Dynamic
                RequiredFieldTypeREV.ControlToValidate = Me.ID
                Select Case RequiredFieldType
                    Case "数据校验"
                        RequiredFieldTypeREV.ValidationExpression = IIf((Me.ValidationExpression IsNot Nothing), Me.ValidationExpression, "^[-]?\d+[.]?\d*$")
                        RequiredFieldTypeREV.ErrorMessage = "数字的格式不正确"
                        Exit Select
                    Case "电子邮箱"
                        RequiredFieldTypeREV.ValidationExpression = IIf((Me.ValidationExpression IsNot Nothing), Me.ValidationExpression, ("^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"))
                        RequiredFieldTypeREV.ErrorMessage = "邮箱的格式不正确"
                        Exit Select
                    Case "移动手机"
                        RequiredFieldTypeREV.ValidationExpression = IIf((Me.ValidationExpression IsNot Nothing), Me.ValidationExpression, "\d{11}")
                        RequiredFieldTypeREV.ErrorMessage = "手机的位数应为11位!"
                        Exit Select
                    Case "家用电话"
                        RequiredFieldTypeREV.ValidationExpression = IIf((Me.ValidationExpression IsNot Nothing), Me.ValidationExpression, "((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}|((\(\d{3}\) ?)|(\d{4}-))?\d{4}-\d{4}")
                        RequiredFieldTypeREV.ErrorMessage = "请依 (XXX)XXX-XXXX 格式或 (XXX)XXXX-XXXX 输入电话号码！"
                        Exit Select
                    Case "身份证号码"
                        RequiredFieldTypeREV.ValidationExpression = IIf((Me.ValidationExpression IsNot Nothing), Me.ValidationExpression, "^\d{15}$|^\d{18}$")
                        RequiredFieldTypeREV.ErrorMessage = "请依15或18位数据的身份证号！"
                        Exit Select
                    Case "网页地址"
                        RequiredFieldTypeREV.ValidationExpression = IIf((Me.ValidationExpression IsNot Nothing), Me.ValidationExpression, "^(http|https)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{1,10}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$")
                        RequiredFieldTypeREV.ErrorMessage = "请输入正确的网址"
                        Exit Select
                    Case "日期"
                        RequiredFieldTypeREV.ValidationExpression = IIf((Me.ValidationExpression IsNot Nothing), Me.ValidationExpression, "^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-))$")
                        RequiredFieldTypeREV.ErrorMessage = "请输入正确的日期,如:2006-1-1"
                        Exit Select
                    Case "日期时间"
                        RequiredFieldTypeREV.ValidationExpression = IIf((Me.ValidationExpression IsNot Nothing), Me.ValidationExpression, "^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-)) (20|21|22|23|[0-1]?\d):[0-5]?\d:[0-5]?\d$")
                        RequiredFieldTypeREV.ErrorMessage = "请输入正确的日期,如: 2006-1-1 23:59:59"
                        Exit Select
                    Case "金额"
                        RequiredFieldTypeREV.ValidationExpression = IIf((Me.ValidationExpression IsNot Nothing), Me.ValidationExpression, "^([0-9]|[0-9].[0-9]{0-2}|[1-9][0-9]*.[0-9]{0,2})$")
                        RequiredFieldTypeREV.ErrorMessage = "请输入正确的金额"
                        Exit Select
                    Case "IP地址"
                        RequiredFieldTypeREV.ValidationExpression = IIf((Me.ValidationExpression IsNot Nothing), Me.ValidationExpression, "^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$")
                        RequiredFieldTypeREV.ErrorMessage = "请输入正确的IP地址"
                        Exit Select
                    Case "IP地址带端口"
                        RequiredFieldTypeREV.ValidationExpression = IIf((Me.ValidationExpression IsNot Nothing), Me.ValidationExpression, "^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9]):\d{1,5}?$")
                        RequiredFieldTypeREV.ErrorMessage = "请输入正确的带端口的IP地址"
                        Exit Select
                End Select
                Me.Controls.AddAt(0, RequiredFieldTypeREV)
            End If

            Select Case CanBeNull
                Case "可为空"
                    Exit Select
                Case "必填"
                    CanBeNullRFV.Display = System.Web.UI.WebControls.ValidatorDisplay.Dynamic
                    CanBeNullRFV.ControlToValidate = Me.ID
                    CanBeNullRFV.ErrorMessage = "<font color=red>请务必输入内容!</font>"
                    Me.Controls.AddAt(0, CanBeNullRFV)
                    Exit Select
                Case Else
                    Exit Select
            End Select

        End Sub

        ''' <summary> 
        ''' 获取焦点的控件ID(如提交按钮等) 
        ''' </summary> 
        <Bindable(True), Category("Appearance"), DefaultValue("")> _
        Public Property SetFocusButtonID() As String
            Get
                Dim o As Object = ViewState(Me.ClientID + "_SetFocusButtonID")
                Return IIf((o Is Nothing), "", o.ToString())
            End Get
            Set(ByVal value As String)
                ViewState(Me.ClientID + "_SetFocusButtonID") = value
                If value <> "" Then
                    Me.Attributes.Add("onkeydown", "if(event.keyCode==13){document.getElementById('" + value + "').focus();}")
                End If
            End Set
        End Property


        ''' <summary> 
        ''' 控件的最大长度属性 
        ''' </summary> 
        <Bindable(True), Category("Appearance"), DefaultValue("")> _
        Public Overloads Overrides Property MaxLength() As Integer
            Get
                Dim o As Object = ViewState("TextBox_MaxLength")
                If o IsNot Nothing Then
                    Dim _maxlength As Integer = CInt(o.ToString)
                    AddAttributes("maxlength", _maxlength.ToString())
                    Return _maxlength
                Else
                    Return -1
                End If
            End Get
            Set(ByVal value As Integer)
                ViewState("TextBox_MaxLength") = value
                AddAttributes("maxlength", value.ToString())
            End Set
        End Property


        ''' <summary> 
        ''' 控件的TextMode属性 
        ''' </summary> 
        <Bindable(False), Category("Behavior"), DefaultValue(TextBoxMode.SingleLine), Description("要滚动的对象。")> _
        Public Overloads Overrides Property TextMode() As TextBoxMode
            Get
                Return MyBase.TextMode
            End Get
            Set(ByVal value As TextBoxMode)
                If value = TextBoxMode.MultiLine Then
                    MyBase.Attributes.Add("onkeyup", "return isMaxLen(this)")
                End If

                MyBase.TextMode = value
            End Set
        End Property

        ''' <summary> 
        ''' 要进行校验的表达式 
        ''' </summary> 
        <Bindable(False), Category("Behavior"), DefaultValue(""), TypeConverter(GetType(RequiredFieldTypeControlsConverter)), Description("要滚动的对象。")> _
        Public Property RequiredFieldType() As String
            Get
                Dim o As Object = ViewState("RequiredFieldType")
                Return IIf((o Is Nothing), "", o.ToString())
            End Get
            Set(ByVal value As String)
                ViewState("RequiredFieldType") = value
            End Set
        End Property


        ''' <summary> 
        ''' 要表达式是否可以为空 
        ''' </summary> 
        <Bindable(False), Category("Behavior"), DefaultValue("可为空"), TypeConverter(GetType(CanBeNullControlsConverter)), Description("要滚动的对象。")> _
        Public Property CanBeNull() As String
            Get
                Dim o As Object = ViewState("CanBeNull")
                Return IIf((o Is Nothing), "", o.ToString())
            End Get
            Set(ByVal value As String)
                ViewState("CanBeNull") = value
            End Set
        End Property


        ''' <summary> 
        ''' 是否进行 ' 号替换 
        ''' </summary> 
        <Bindable(True), Category("Appearance"), DefaultValue("")> _
        Public Property IsReplaceInvertedComma() As Boolean
            Get
                Dim o As Object = ViewState("IsReplaceInvertedComma")
                If o Is Nothing OrElse o.ToString().Trim() = "" Then
                    Return True
                Else
                    Return IIf(o.ToString().ToLower() = "true", True, False)
                End If
            End Get
            Set(ByVal value As Boolean)
                ViewState("IsReplaceInvertedComma") = value
            End Set
        End Property


        ''' <summary> 
        ''' 有效校验表达式 
        ''' </summary> 
        <Bindable(True), Category("Appearance"), DefaultValue("")> _
        Public Property ValidationExpression() As String
            Get
                Dim o As Object = ViewState("ValidationExpression")
                If o Is Nothing OrElse o.ToString().Trim() = "" Then
                    Return Nothing
                Else
                    Return o.ToString().ToLower()
                End If
            End Get
            Set(ByVal value As String)
                ViewState("ValidationExpression") = value
            End Set
        End Property

        ''' <summary> 
        ''' 文本内容属性 
        ''' </summary> 
        <Bindable(True), Category("Appearance"), DefaultValue("")> _
        Public Overloads Overrides Property Text() As String
            Get

                '进行强制日期格式的转换 
                If Me.RequiredFieldType = "日期" Then
                    Try
                        Return DateTime.Parse(MyBase.Text).ToString("yyyy-MM-dd")
                    Catch
                        Return "1900-1-1"
                    End Try
                End If

                '进行强制日期时间格式的转换 
                If Me.RequiredFieldType = "日期时间" Then
                    Try
                        Return DateTime.Parse(MyBase.Text).ToString("yyyy-MM-dd HH:mm:ss")
                    Catch
                        Return "1900-1-1 00:00:00"
                    End Try
                Else
                    Return IIf(IsReplaceInvertedComma, MyBase.Text.Replace("'", "''").Trim(), MyBase.Text)
                End If
            End Get
            Set(ByVal value As String)
                '进行强制日期格式的转换 
                If Me.RequiredFieldType.IndexOf("日期") >= 0 Then
                    Try
                        MyBase.Text = DateTime.Parse(value).ToString("yyyy-MM-dd")
                    Catch
                        MyBase.Text = ""
                    End Try
                End If

                '进行强制日期时间格式的转换 
                If Me.RequiredFieldType.IndexOf("日期时间") >= 0 Then
                    Try
                        MyBase.Text = DateTime.Parse(value).ToString("yyyy-MM-dd HH:mm:ss")
                    Catch
                        MyBase.Text = ""
                    End Try
                Else
                    MyBase.Text = value
                End If
            End Set
        End Property


        ''' <summary> 
        ''' 列数属性 
        ''' </summary> 
        <Bindable(True), Category("Appearance"), DefaultValue(30)> _
        Public Property Cols() As Integer
            Get
                Return MyBase.Columns
            End Get
            Set(ByVal value As Integer)
                MyBase.Columns = value
            End Set
        End Property

        Private _size As Integer = 30
        ''' <summary> 
        ''' 宽度属性 
        ''' </summary> 
        <Bindable(True), Category("Appearance"), DefaultValue(30)> _
        Public Property Size() As Integer
            Get
                Return _size
            End Get
            Set(ByVal value As Integer)
                _size = value
            End Set
        End Property


        Private _maximumValue As String = Nothing
        ''' <summary> 
        ''' 最大值属性 
        ''' </summary> 
        <Bindable(True), Category("Appearance"), DefaultValue("")> _
        Public Property MaximumValue() As String
            Get
                Return _maximumValue
            End Get
            Set(ByVal value As String)
                _maximumValue = value
            End Set
        End Property

        Private _minimumValue As String = Nothing
        ''' <summary> 
        ''' 最小值属性 
        ''' </summary> 
        <Bindable(True), Category("Appearance"), DefaultValue("")> _
        Public Property MinimumValue() As String
            Get
                Return _minimumValue
            End Get
            Set(ByVal value As String)
                _minimumValue = value
            End Set
        End Property


        Private _hintTitle As String = ""
        ''' <summary> 
        ''' 提示框标题 
        ''' </summary> 
        <Bindable(True), Category("Appearance"), DefaultValue("")> _
        Public Property HintTitle() As String Implements IWebControl.HintTitle
            Get
                Return _hintTitle
            End Get
            Set(ByVal value As String)
                _hintTitle = value
            End Set
        End Property


        Private _hintInfo As String = ""
        ''' <summary> 
        ''' 提示框内容 
        ''' </summary> 
        <Bindable(True), Category("Appearance"), DefaultValue("")> _
        Public Property HintInfo() As String Implements IWebControl.HintInfo
            Get
                Return _hintInfo
            End Get
            Set(ByVal value As String)
                _hintInfo = value
            End Set
        End Property


        Private _hintLeftOffSet As Integer = 0
        ''' <summary> 
        ''' 提示框左侧偏移量 
        ''' </summary> 
        <Bindable(True), Category("Appearance"), DefaultValue(0)> _
        Public Property HintLeftOffSet() As Integer Implements IWebControl.HintLeftOffSet
            Get
                Return _hintLeftOffSet
            End Get
            Set(ByVal value As Integer)
                _hintLeftOffSet = value
            End Set
        End Property

        Private _hintTopOffSet As Integer = 0
        ''' <summary> 
        ''' 提示框顶部偏移量 
        ''' </summary> 
        <Bindable(True), Category("Appearance"), DefaultValue(0)> _
        Public Property HintTopOffSet() As Integer Implements IWebControl.HintTopOffSet
            Get
                Return _hintTopOffSet
            End Get
            Set(ByVal value As Integer)
                _hintTopOffSet = value
            End Set
        End Property

        Private _hintShowType As String = "up"
        '或"down" 
        ''' <summary> 
        ''' 提示框风格,up(上方显示)或down(下方显示) 
        ''' </summary> 
        <Bindable(True), Category("Appearance"), DefaultValue("up")> _
        Public Property HintShowType() As String
            Get
                Return _hintShowType
            End Get
            Set(ByVal value As String)
                _hintShowType = value
            End Set
        End Property

        Private _hintHeight As Integer = 50
        ''' <summary> 
        ''' 提示框高度 
        ''' </summary> 
        <Bindable(True), Category("Appearance"), DefaultValue(130)> _
        Public Property HintHeight() As Integer Implements IWebControl.HintHeight
            Get
                Return _hintHeight
            End Get
            Set(ByVal value As Integer)
                _hintHeight = value
            End Set
        End Property


        ''' <summary> 
        ''' 输出html,在浏览器中显示控件 
        ''' </summary> 
        ''' <param name="output"> 要写出到的 HTML 编写器 </param> 
        Protected Overloads Overrides Sub Render(ByVal output As HtmlTextWriter)

            '当为TextArea时，maxlength属性可能失效，所以采用js进行长度限制 
            If Me.TextMode = TextBoxMode.MultiLine Then
                output.WriteLine("<script type=""text/javascript"">")
                output.WriteLine("function isMaxLen(o){")
                output.WriteLine("var nMaxLen=o.getAttribute? parseInt(o.getAttribute(""maxlength"")):"""";")
                output.WriteLine(" if(o.getAttribute && o.value.length>nMaxLen){")
                output.WriteLine(" o.value=o.value.substring(0,nMaxLen)")
                output.WriteLine("}}</script>")

                Me.AddAttributes("rows", Rows.ToString())
                Me.AddAttributes("cols", Cols.ToString())
            Else
                If Me.Size > 0 Then
                    Me.AddAttributes("size", Me.Size.ToString())
                End If
            End If


            If Me.HintInfo <> "" Then
                Me.AddAttributes("onmouseover", "showhintinfo(this," + Me.HintLeftOffSet + "," + Me.HintTopOffSet + ",'" + Me.HintTitle + "','" + Me.HintInfo + "','" + Me.HintHeight + "','" + Me.HintShowType + "')")
                Me.AddAttributes("onmouseout", "hidehintinfo()")
            End If

            MyBase.Render(output)

            RenderChildren(output)

        End Sub

    End Class

End Namespace